export function createContainer(
    containerInfo: Container,
    isConcurrent: boolean,
    hydrate: boolean,
): OpaqueRoot {
    return createFiberRoot(containerInfo, isConcurrent, hydrate); //5
}

/**
 * @description: 5
 * @param {type} 
 * @return: 
 */
function ReactRoot(
    container: Container,
    isConcurrent: boolean,
    hydrate: boolean,
) {
    const root = DOMRenderer.createContainer(container, isConcurrent, hydrate); //FiberRoot对象
    this._internalRoot = root;
}


// 调用该方法
ReactRoot.prototype.render = function (
    children: ReactNodeList,
    callback: ? () => mixed,
): Work {
    const root = this._internalRoot;
    const work = new ReactWork();
    callback = callback === undefined ? null : callback;
    if (__DEV__) {
        warnOnInvalidCallback(callback, 'render');
    }
    if (callback !== null) {
        work.then(callback);
    }
    DOMRenderer.updateContainer(children, root, null, work._onCommit);
    return work;
};


ReactRoot.prototype.unmount = function (callback: ? () => mixed): Work {
    const root = this._internalRoot;
    const work = new ReactWork();
    callback = callback === undefined ? null : callback;
    if (__DEV__) {
        warnOnInvalidCallback(callback, 'render');
    }
    if (callback !== null) {
        work.then(callback);
    }
    DOMRenderer.updateContainer(null, root, null, work._onCommit);
    return work;
};

/**
 * @description: 7 
 * @param {type} 
 * @return: 
 */
ReactRoot.prototype.legacy_renderSubtreeIntoContainer = function (
    parentComponent,
    children,
    callback,
){
    const root = this._internalRoot;
    const work = new ReactWork();
    callback = callback === undefined ? null : callback;
    if (callback !== null) {
        work.then(callback);
    }
    DOMRenderer.updateContainer(children, root, parentComponent, work._onCommit); // 8
    return work;
};


ReactRoot.prototype.createBatch = function (): Batch {
    const batch = new ReactBatch(this);
    const expirationTime = batch._expirationTime;

    const internalRoot = this._internalRoot;
    const firstBatch = internalRoot.firstBatch;
    if (firstBatch === null) {
        internalRoot.firstBatch = batch;
        batch._next = null;
    } else {
        // Insert sorted by expiration time then insertion order
        let insertAfter = null;
        let insertBefore = firstBatch;
        while (
            insertBefore !== null &&
            insertBefore._expirationTime <= expirationTime
        ) {
            insertAfter = insertBefore;
            insertBefore = insertBefore._next;
        }
        batch._next = insertBefore;
        if (insertAfter !== null) {
            insertAfter._next = batch;
        }
    }

    return batch;
};